package com.example.makerspace.manager;

import com.alibaba.fastjson.JSONObject;
import com.example.makerspace.dao.ExamQuestionDAO;
import com.example.makerspace.domain.ExamDO;
import com.example.makerspace.domain.ExamQuestionDO;
import com.example.makerspace.dto.ExamQuestionDTO;
import com.example.makerspace.dto.Result;
import com.example.makerspace.enums.ResultCodeEnum;
import com.google.common.util.concurrent.AtomicDouble;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


@Component
public class ExamQuestionManager extends BaseManager<ExamQuestionDO, ExamQuestionDTO> {

    @Resource
    private ExamQuestionDAO examQuestionDAO;

    @Resource
    private ExamManager examManager;

    @PostConstruct
    public void init(){
        this.baseDAO = examQuestionDAO;
    }


    public Result addExamQuestion(ExamQuestionDTO examQuestionDTO) {
        ExamDO examDO = examManager.selectById(examQuestionDTO.getExamId());
        if(examDO == null){
            return Result.error(ResultCodeEnum.EXAM_NOT_EXIST);
        }
        ExamQuestionDO examQuestionDO = examQuestionDAO.selectDuplicate(examQuestionDTO);
        if(examQuestionDO != null){
            return Result.error(ResultCodeEnum.QUESTION_EXIST);
        }
        return addDO(examQuestionDTO);
    }

    public Result updateExamQuestion(ExamQuestionDTO examQuestionDTO) {
        ExamDO examDO = examManager.selectById(examQuestionDTO.getExamId());
        if(examDO == null){
            return Result.error(ResultCodeEnum.EXAM_NOT_EXIST);
        }
        ExamQuestionDO examQuestionDO = examQuestionDAO.selectById(examQuestionDTO.getId());
        if(examQuestionDO == null){
            return Result.error(ResultCodeEnum.QUESTION_NOT_EXIST);
        }
        Optional.ofNullable(examQuestionDTO.getQuestion()).ifPresent(examQuestionDO::setQuestion);
        Optional.ofNullable(examQuestionDTO.getAnswer()).ifPresent(examQuestionDO::setAnswer);
        Optional.ofNullable(examQuestionDTO. getOptions()).ifPresent(examQuestionDO::setOptions);
        return updateDO(examQuestionDO);
    }

    public Result tobDetail(ExamQuestionDTO examQuestionDTO) {
        return Result.success(questionList(examQuestionDTO));
    }

    public Result tocDetail(ExamQuestionDTO examQuestionDTO) {
        List<ExamQuestionDTO> examQuestionDTOS = questionList(examQuestionDTO);
        Optional.ofNullable(examQuestionDTOS).orElse(Collections.emptyList())
                .forEach(examQuestion -> {
                    examQuestion.setAnswer(null);
                    examQuestion.setModifyTime(null);
                    examQuestion.setCreateTime(null);
                });
        return Result.success(examQuestionDTOS);
    }

    public List<ExamQuestionDTO> questionList(ExamQuestionDTO examQuestionDTO){
        ExamDO examDO = examManager.selectById(examQuestionDTO.getExamId());
        if(examDO == null){
            return null;
        }
        Integer examId = examQuestionDTO.getExamId();
        List<ExamQuestionDO> examQuestionDOS = examQuestionDAO.selectByExamId(examId);
        return Optional.ofNullable(examQuestionDOS).orElse(Collections.emptyList())
                .stream().map(this::convert2DTO).collect(Collectors.toList());
    }

    public Result judge(Map<String, Object> params) {
        JSONObject jsonObject = new JSONObject();
        Integer examId = MapUtils.getInteger(params, "examId");
        ExamDO examDO = examManager.selectById(examId);
        if (examDO == null) {
            return Result.error(ResultCodeEnum.EXAM_NOT_EXIST);
        }
        Map<Integer, String> answerMap = Optional.ofNullable(examQuestionDAO.selectByExamId(examId))
                .orElse(Collections.emptyList())
                .stream().collect(Collectors.toMap(ExamQuestionDO::getId, ExamQuestionDO::getAnswer, (x, y) -> x));
        double s = (double) 100 / answerMap.size();
        Object answersObj = MapUtils.getObject(params, "answers");
        String jsonString = JSONObject.toJSONString(answersObj);
        List<ExamQuestionDTO> answers = JSONObject.parseArray(jsonString, ExamQuestionDTO.class);
        AtomicDouble score = new AtomicDouble();
        Optional.ofNullable(answers).orElse(Collections.emptyList())
                .forEach(examQuestionDTO -> {
                    String answer = answerMap.get(examQuestionDTO.getId());
                    Optional.ofNullable(answer).ifPresent(a -> {
                        if(a.equals(examQuestionDTO.getAnswer())){
                            score.addAndGet(s);
                        }
                    });
                });
        jsonObject.put("score", Math.round(score.get()));
        return Result.success(jsonObject);
    }
}
